﻿using System;
using System.Data.SqlClient;
using System.Linq;
using System.Threading;
using Common.Logging;

using Newtonsoft.Json;
using OutDbContext;
using Rmq.Center;
using User.Api.BizExtensions;
using User.Api.Helpers;
using User.Api.Helpers.WeixinPayV3.WxResult;

namespace Out.TaskRunner.RmqWorkers
{
    public class OrderRefundingPickupFailedWorker : IWorker
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(OrderRefundingPickupFailedWorker));

        public void Start(CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
            {
                return;
            }

            using (var consumer = new OrderRefundingPickupFailedConsumer())
            {
                consumer.Subscribe((id, count, dt, msg, channel) =>
                {
                    if (msg.OrderType == OrderType.挂号订单)
                    {
                        return ProcessRegOrder(msg.OrderId, channel);
                    }
                    else if (msg.OrderType == OrderType.门诊缴费订单)
                    {
                        return ProcessBillOrder(msg.OrderId, channel);
                    }
                    
                    return new ConsumedResult { Ack = true };
                });

                while (true)
                {
                    if (ct.IsCancellationRequested)
                    {
                        break;
                    }

                    Thread.Sleep(50);
                }
            }
        }

        private ConsumedResult ProcessRegOrder(int orderId, WrapperChannel channel)
        {
            OrderSummary order;
            string openId;
            using (var ctx = new HzfyWeiXinEntities())
            {
                order = ctx.ApptOrder.Where(x => x.Id == orderId).
                    Select(x => new OrderSummary
                    {
                        OrderStatus = x.OrderStatus,
                        PayState = x.PayState,
                        Id = x.Id,
                        WxTransactionId = x.WxTransactionId,
                        WxUserId = x.WxUserId,
                        OrderNo = x.OrderNo,
                        SumFee = x.SumFee
                    }).FirstOrDefault();
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                openId = ctx.WxUser.Where(x => x.Id == order.WxUserId).Select(x => x.OpenId).FirstOrDefault();
                // 退款中
                //order.OrderStatus = ApptOrderExtensions.OrderStatus.退款中.ToInt32();
                //order.PayState = ApptOrderExtensions.PayState.退款中.ToInt32().ToString();
                //order.RefundReason = "取号失败而退款";
                //ctx.SaveChanges();

                SqlParameter[] para =
                {
                    new SqlParameter("@OrderStatus", ApptOrderExtensions.OrderStatus.退款中.ToInt32()),
                    new SqlParameter("@PayState", ApptOrderExtensions.PayState.退款中.ToInt32().ToString()),
                    new SqlParameter("@RefundReason", "取号失败而退款"),
                    new SqlParameter("@OrderId", order.Id)
                };
                ctx.Database.ExecuteSqlCommand(
                    "Update ApptOrder set OrderStatus= @OrderStatus,PayState = @PayState,RefundReason=@RefundReason where Id=@OrderId",
                    para);


            }

            DoRefundResult refundResult = new DoRefundResult();
            try
            {

                refundResult = WeixinPayV3Helper.DoRefund("AP" + order.OrderNo, order.WxTransactionId,
                    "AP" + order.OrderNo, (order.SumFee*100).ToInt32(), (order.SumFee*100).ToInt32());

            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                return new ConsumedResult
                {
                    Ack = false,
                    Delay = 1000
                };
            }
            //退款成功 4,10
            //退款处理中 8 9 11
            if (refundResult.RefundStatus == 4 || refundResult.RefundStatus == 10 ||
                refundResult.RefundStatus == 8 || refundResult.RefundStatus == 9 || refundResult.RefundStatus == 11)
            {
                // 退款成功
                //order.OrderStatus = ApptOrderExtensions.OrderStatus.退款成功.ToInt32();
                //order.RefundReason = "取号失败而退款";//reason == 4 ? "窗口退号" : "因退号而退款";
                //order.PayState = ApptOrderExtensions.PayState.已退款.ToInt32().ToString();
                //order.RefundTime = DateTime.Now;
                //order.WxRefundId = refundResult.RefundId;
                //ctx.SaveChanges();
                using (var ctx = new HzfyWeiXinEntities())
                {
                    SqlParameter[] para = new SqlParameter[]
                    {
                        new SqlParameter("@OrderStatus", ApptOrderExtensions.OrderStatus.退款成功.ToInt32()),
                        new SqlParameter("@PayState", ApptOrderExtensions.PayState.已退款.ToInt32().ToString()),
                        new SqlParameter("@RefundReason", "取号失败而退款"),
                        new SqlParameter("@RefundTime", DateTime.Now),
                        new SqlParameter("@WxRefundId", refundResult.RefundId),
                        new SqlParameter("@OrderId", order.Id)
                    };
                    ctx.Database.ExecuteSqlCommand(
                        "Update ApptOrder set OrderStatus= @OrderStatus,PayState = @PayState,RefundReason=@RefundReason, " +
                        "RefundTime = @RefundTime,WxRefundId = @WxRefundId where Id=@OrderId", para);
                }

                // RMQ 发送用户退费成功通知
                var msgProducer = new UserMessageProducer();
                msgProducer.Publish(new UserMessageMsg
                {
                    Type = UserMessageType.挂号失败退费成功通知,
                    OrderId = order.Id
                });
                if (!string.IsNullOrEmpty(openId))
                {
                    //TenpayV2Helper.DoDeliverNotify(wxuser.OpenId, order.WxTransactionId,
                    //"AP" + order.OrderNo, "0", "RefundSucceed");
                    WeixinPayV3Helper.DoDeliveryNotify(openId, order.WxTransactionId,
                        "AP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000)/10000000)
                            .ToString(), "0", "RefundSucceed");
                }
                return new ConsumedResult
                {
                    Ack = true
                };
            }
            //退款失败 3，5，6
            //转入代发 7
            if (refundResult.RefundStatus == 7 ||
                refundResult.RefundStatus == 3 || refundResult.RefundStatus == 5 || refundResult.RefundStatus == 6)
            {
                // 退款失败
                //order.OrderStatus = ApptOrderExtensions.OrderStatus.退款失败.ToInt32();
                //order.PayState = ApptOrderExtensions.PayState.退款失败.ToInt32().ToString();
                //ctx.SaveChanges();
                using (var ctx = new HzfyWeiXinEntities())
                {
                    SqlParameter[] para = new SqlParameter[]
                    {
                        new SqlParameter("@OrderStatus", ApptOrderExtensions.OrderStatus.退款失败.ToInt32()),
                        new SqlParameter("@PayState", ApptOrderExtensions.PayState.退款失败.ToInt32().ToString()),
                        new SqlParameter("@OrderId", order.Id)
                    };
                    ctx.Database.ExecuteSqlCommand(
                        "Update ApptOrder set OrderStatus= @OrderStatus,PayState = @PayState where Id=@OrderId",
                        para);

                }
                if (!string.IsNullOrEmpty(openId))
                {
                    //TenpayV2Helper.DoDeliverNotify(wxuser.OpenId, order.WxTransactionId,
                    //"AP" + order.OrderNo, "0", "RefundFailed");
                    WeixinPayV3Helper.DoDeliveryNotify(openId, order.WxTransactionId,
                        "AP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000)/10000000)
                            .ToString(), "0", "RefundFailed");
                }
                return new ConsumedResult
                {
                    Ack = true
                };
            }

            // 1，2：未确定，需要商户原退款单号重新发起
            if (refundResult.RefundStatus == 1 || refundResult.RefundStatus == 2)
            {
                return new ConsumedResult
                {
                    Ack = false,
                    Delay = 1000
                };
            }


            return new ConsumedResult
            {
                Ack = true
            };
        }

        private ConsumedResult ProcessBillOrder(int orderId, WrapperChannel channel)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.BillOrder.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                var wxuser = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                // 退款中
                order.OrderStatus = BillOrderExtensions.OrderStatus.退款中.ToInt32();
                order.PayState = BillOrderExtensions.PayState.退款中.ToInt32().ToString();
                ctx.SaveChanges();

                var payFee = (order.PrescMoney.GetValueOrDefault() * 100).ToInt32().ToString();


                DoRefundResult refundResult=new DoRefundResult();
                try
                {
                    refundResult = WeixinPayV3Helper.DoRefund("BL" + order.OrderNo, order.WxTransactionId,
                      "BL" + order.OrderNo, payFee.ToInt32(), payFee.ToInt32());
                    
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    return new ConsumedResult
                    {
                        Ack = false,
                        Delay = 1000
                    };
                }

                // 1，2：未确定，需要商户原退款单号重新发起
                if (refundResult.RefundStatus == 1 || refundResult.RefundStatus == 2)
                {
                    return new ConsumedResult
                    {
                        Ack = false,
                        Delay = 1000
                    };
                }
                //退款成功 4,10
                //退款处理中 8 9 11
                if (refundResult.RefundStatus == 4 || refundResult.RefundStatus == 10 ||
                    refundResult.RefundStatus == 8 || refundResult.RefundStatus == 9 || refundResult.RefundStatus == 11)
                {
                    // 退款成功
                    order.OrderStatus = BillOrderExtensions.OrderStatus.退款成功.ToInt32();
                    order.PayState = BillOrderExtensions.PayState.已退款.ToInt32().ToString();
                    order.RefundTime = DateTime.Now;
                    order.WxRefundId = refundResult.RefundId;
                    ctx.SaveChanges();

                    // RMQ 发送用户退费成功通知
                    var messageProducer = new UserMessageProducer();
                    messageProducer.Publish(new UserMessageMsg
                    {
                        OrderId = order.Id,
                        Type = UserMessageType.缴费失败退款成功通知
                    });
               
                    if (wxuser != null)
                    {
                        //TenpayV2Helper.DoDeliverNotify(wxuser.OpenId, order.WxTransactionId,
                        //"BL" + order.OrderNo, "0", "RefundSucceed");
                        WeixinPayV3Helper.DoDeliveryNotify(wxuser.OpenId, order.WxTransactionId,
                 "BL" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                                  .ToString(), "0", "RefundSucceed");

                    }
                }
                //退款失败 3，5，6
                //转入代发 7
                if (refundResult.RefundStatus == 7 ||
                    refundResult.RefundStatus == 3 || refundResult.RefundStatus == 5 || refundResult.RefundStatus == 6)
                {
                    // 退款失败
                    order.OrderStatus = BillOrderExtensions.OrderStatus.退款失败.ToInt32();
                    order.PayState = BillOrderExtensions.PayState.退款失败.ToInt32().ToString();
                    ctx.SaveChanges();
                    if (wxuser != null)
                    {
                        //TenpayV2Helper.DoDeliverNotify(wxuser.OpenId, order.WxTransactionId,
                        //"BL" + order.OrderNo, "0", "RefundFailed");
                        WeixinPayV3Helper.DoDeliveryNotify(wxuser.OpenId, order.WxTransactionId,
             "BL" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                              .ToString(), "0", "RefundFailed");
                    }
                }
                 
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }

        public class OrderSummary
        {
            public int OrderStatus { get; set; }
            public string PayState { get; set; }
            public int Id { get; set; }
            public string WxTransactionId { get; set; }
            public long? WxUserId { get; set; }
            public string OrderNo { get; set; }
            public decimal? SumFee { get; set; }
        }
    }
}